package br.com.mmm.javacenter.framework.view.servlet;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javassist.bytecode.ConstantAttribute;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.displaytag.tags.TableTagParameters;
import org.displaytag.util.ParamEncoder;

import br.com.mmm.javacenter.framework.entity.EntidadeBase;
import br.com.mmm.javacenter.framework.util.Atributo;
import br.com.mmm.javacenter.framework.view.ContextAttributes;
import br.com.mmm.javacenter.framework.view.taglib.helper.Alerta;

import com.sun.security.auth.UserPrincipal;

public class ServletFacade {
	private HttpServletRequest request = null;
	private HttpServletResponse response = null;
	private String action;
	
	public ServletFacade(final HttpServletRequest request, final HttpServletResponse response) {
		this.request = (HttpServletRequest) request;
		this.response = (HttpServletResponse) response;
		this.request.setAttribute("sf", this);
		this.request.setAttribute(ContextAttributes.REQUEST_ALERTAS, new ArrayList<Alerta>());
		response.setHeader("Cache-Control", "no-cache, post-check=0, pre-check=0");
		response.setHeader("Pragma", "no-cache");
		response.setHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT");
	}
	public void include(final String page) {
		try {
			this.request.getRequestDispatcher(page).include(this.request, this.response);
		} catch (final ServletException e) {
			e.printStackTrace();
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}
	public void forward() {
		try {
			this.request.setAttribute(ContextAttributes.REQUEST_CONTROLLER,getController());
			this.request.setAttribute(ContextAttributes.REQUEST_ACTION,getAction());
			this.request.getRequestDispatcher("/jsp/common/principal.jsp").forward(this.request, this.response);
		} catch (final ServletException e) {
			e.printStackTrace();
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}
	
	public String getAction() {
		if(action == null){
			if (this.getPath().length == 2){
				action = "doMain";
			}else{
				action = this.getPath()[2];
			}
		}else{
			return action;	
		}
		return action;
	}
	

	public void setAction(String action) {
		this.action = action;
	}
	public String getActionClean() {
		if(action == null){
			if (this.getPath().length == 2){
				action = "doMain";
			}else{
				action = this.getPath()[2];
			}
		}else{
			return action;	
		}
		return action;
	}
	public BigDecimal getBigDecimalParameter(final String parameter){
		return new BigDecimal(this.request.getParameter(parameter));
	}

	public String getCompletePath(){
		return getServerPath() + request.getAttribute(ContextAttributes.REQUEST_CONTROLLER) + "/" + request.getAttribute(ContextAttributes.REQUEST_ACTION) + ContextAttributes.SUFFIX_FRAMEWORK ;
	}
	public String getServerPath(String controller,String action,Atributo ... atributo){
		String ret = getContextPath() + controller + "/" + action + ContextAttributes.SUFFIX_FRAMEWORK + "?";
		for(Atributo atributo2:atributo){
			ret += atributo2.getName() + "=" + atributo2.getValue() + "&";
		}
		return response.encodeURL(ret);
	}
	public String getServerPath(String controller,String action){
		return request.getServerName() + ":" + request.getServerPort() + getContextPath() + controller + "/" + action + ContextAttributes.SUFFIX_FRAMEWORK;
	}
	public String getServerPath(String controller){
		return request.getServerName() + ":" + request.getServerPort() + getContextPath() + controller + "/";
	}
	public String getServerPath(){
		return request.getServerName() + ":" + request.getServerPort() + getContextPath();
	}
	public String getContextPath() {
		return  this.request.getContextPath() + "/";
	}
	
	public UserPrincipal getUsuarioLogado(){
		return (UserPrincipal) request.getUserPrincipal();
	}
	
	public String getController() {
		String controller = null;
		if(this.getPath().length >= 1){
			controller = this.getPath()[1];
		}
		this.request.setAttribute("$_controller", controller);
		return controller;
	}

	@SuppressWarnings("deprecation")
	public Date getDateParameter(final String parameter){
		return  new Date(this.request.getParameter(parameter));
	}


	public double getDoubleParameter(final String parameter){
		return Integer.parseInt(this.request.getParameter(parameter));
	}
	public int getIntParameter(final String parameter){
		if (this.request.getParameter(parameter) == null){
			return 0;
		}
		return Integer.parseInt(this.request.getParameter(parameter));
	}
	public Integer getIntParamID(){
		return Integer.parseInt(this.getParamID());
	}
	public Long getLongParamID(){
		return new Long(this.getParamID());
	}
	public Locale getLocale() {
		return this.request.getLocale();
	}
	public Object getModel(final Class<? extends Object> type){
		Object o = null;
		return o;
	}
	public String getPacoteControllers() {
		return "br.com.prime.controller.";
	}
	public String getPageDefault() {
		String pageTmp;
		if (this.getPath().length == 2){
			pageTmp = "index";
		}else{
			if ((this.getPath()[2].substring(0,1).toLowerCase() + this.getPath()[2].substring(1)).equalsIgnoreCase("main")){
				pageTmp = "index";
			}else{
				pageTmp = this.getPath()[2].substring(0,1).toLowerCase() + this.getPath()[2].substring(1);
			}
		}
		return pageTmp;
	}
	public String getParameter(final String parameter){
		return this.request.getParameter(parameter);
	}
	public Integer[] getParameterIntValues(final String parameter){

		String[] def = null;
		if (this.request.getParameterValues(parameter) == null){
				if(this.request.getAttribute("$_param_" + parameter) != null)
					def = this.request.getAttribute("$_param_" + parameter).toString().split(",");
				else 
					def = null;
		}else{
			def = this.request.getParameterValues(parameter);
		}
		Integer[] items = null;
		if (def != null){
			items = new Integer[def.length];
			int i =0;
			for(String value:def){
				try{
					items[i] = Integer.parseInt(value);
				}catch(NumberFormatException nfe){
					items[i] = 0;
				}
				i++;
			}
		}
		return items;
	}
	public Long[] getParameterLongValues(final String parameter){
		String[] def = null;
		if (this.request.getParameterValues(parameter) == null){
				if(this.request.getAttribute("$_param_" + parameter) != null)
					def = this.request.getAttribute("$_param_" + parameter).toString().split(",");
				else 
					def = null;
		}else{
			def = this.request.getParameterValues(parameter);
		}
		Long[] items = null;
		if (def != null){
			items = new Long[def.length];
			int i =0;
			for(String value:def){
				try{
					items[i] = Long.parseLong(value);
				}catch(NumberFormatException nfe){
					items[i] = 0L;
				}
				i++;
			}
		}
		return items;
	}
	@SuppressWarnings("unchecked")
	public String[] getParameterValuesNameStartsWith(final String parameter){
		Enumeration<String> params = this.request.getParameterNames();
		List<String> paramsReal = new LinkedList<String>();
		while(params.hasMoreElements()){
			String tmp = params.nextElement();
			if (tmp.startsWith(parameter)){
				if (!paramsReal.contains(tmp))
					paramsReal.add(tmp);
			}
		}
		Collections.sort(paramsReal);
		if(paramsReal.size() == 0){
			return null;
		}
		int size = 0;
		for(String p :paramsReal){
			if(request.getParameterValues(p) != null && request.getParameterValues(p).length > 1){
				size+=request.getParameterValues(p).length;
			}else{
				size++;
			}
		}
		int pos=0;
		String[] retorno = new String[size]; 
		for(String p :paramsReal){
			if(request.getParameterValues(p) != null && request.getParameterValues(p).length > 1){
				for(String p2:request.getParameterValues(p)){
					retorno[pos++] = p2;
				}
			}else{
				retorno[pos++] =  this.request.getParameter(p);
			}
		}
		return retorno;
	}
	@SuppressWarnings("unchecked")
	public String[] getParameterValuesNameRegularExpression(final String expression){
		Enumeration<String> params = this.request.getParameterNames();
		List<String> paramsReal = new LinkedList<String>();
		Pattern pattern = Pattern.compile(expression);
		while(params.hasMoreElements()){
			String tmp = params.nextElement();
			Matcher matcher = pattern.matcher(tmp);
			boolean aprovado = matcher.find();
			System.out.println(tmp + " - " + expression + " = " + aprovado);
			if (aprovado){
				if (!paramsReal.contains(tmp))
					paramsReal.add(tmp);
			}
		}
		Collections.sort(paramsReal);
		if(paramsReal.size() == 0){
			return null;
		}
		int size = 0;
		for(String p :paramsReal){
			if(request.getParameterValues(p) != null && request.getParameterValues(p).length > 1){
				size+=request.getParameterValues(p).length;
			}else{
				size++;
			}
		}
		int pos=0;
		String[] retorno = new String[size]; 
		for(String p :paramsReal){
			if(request.getParameterValues(p) != null && request.getParameterValues(p).length > 1){
				for(String p2:request.getParameterValues(p)){
					retorno[pos++] = p2;
				}
			}else{
				retorno[pos++] =  this.request.getParameter(p);
			}
		}
		return retorno;
	}
	public String[] getParameterValues(final String parameter){
		if (this.request.getParameterValues(parameter) == null){
				if(this.request.getAttribute("$_param_" + parameter) != null)
					return this.request.getAttribute("$_param_" + parameter).toString().split(",");
				else 
					return null;
		}else{
			return this.request.getParameterValues(parameter);
		}
	}
	@SuppressWarnings("unchecked")
	public Enumeration<String> getRequestParametersNames(){
		return this.request.getParameterNames();
	}
	public String getParamID(){
		String pageID = "";
		if (this.getPath().length == 4){
			pageID = this.getPath()[3].split("\\.")[0];
		}
		return pageID;
	}
	public String[] getPath() {
		 String uri = this.request.getRequestURI().substring(1);
		if (uri.indexOf(";JSESSIONID=") != -1){
			uri = uri.substring(0,uri.indexOf(";JSESSIONID="));
			return uri.substring(0,uri.length()-5).split("/");
		}else{
			return uri.substring(0,uri.length()-5).split("/");
		}
	}
	public HttpSession getSession() {
		return this.request.getSession();
	}
	public HttpSession getSession(final boolean value) {
		return this.request.getSession(value);
	}
	public Object getSessionAttribute(final String sessionObject) {
		return this.getSession().getAttribute(sessionObject);
	}
	public void sendRedirect(final String query) {
		try {
			this.response.sendRedirect(query);
		} catch (final IOException e) {
			e.printStackTrace();
		}
	}
	public String getIP(){
		return request.getRemoteHost();
		
	}
	public void setAttribute(final String string, final Object o) {
		this.request.setAttribute(string, o);
	}
	public void setSessionAttribute(final String string, final Object o) {
		this.getSession().setAttribute(string,o);
	}
	public String getUrl() {
		StringBuffer sb = new StringBuffer();
		sb.append("http://");
		sb.append(request.getServerName());
		sb.append(":");
		sb.append(request.getServerPort());
		sb.append(request.getContextPath());
		return sb.toString();
	}
	public String getUrl(String action) {
		StringBuffer sb = new StringBuffer();
		sb.append(getUrl());
		sb.append("/");
		sb.append(getController());
		sb.append("/");
		sb.append(action + ".do");
		return sb.toString();
	}
	public String getUrl(String controller,String action) {
		StringBuffer sb = new StringBuffer();
		sb.append(getUrl());
		sb.append("/");
		sb.append(controller);
		sb.append("/");
		sb.append(action + ".do");
		return sb.toString();
	}
	
	public long getLongParameter(String parameter) {
		try{
			return Long.parseLong(getParameter(parameter));
		}catch (Exception e) {
			return new Long(0L);
		}
	}
	public boolean getBooleanParameter(String name) {
		if (getParameter(name)!= null){
			String value = getParameter(name);
			if (value.equalsIgnoreCase("true")){
				return true;
			}else if(value.equalsIgnoreCase("0")){
				return true;
			}else if(value.equalsIgnoreCase("yes")){
				return true;
			}else if(value.equalsIgnoreCase("sim")){
				return true;
			}else if(value.equalsIgnoreCase("s")){
				return true;
			}else{
				return false; 
			} 
		}else{
			return false;
		}
	}
	public Object getAttribute(String name){
		return request.getAttribute(name);
	}
	public HttpServletRequest getRequest() {
		return request;
	}
	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}
	public HttpServletResponse getResponse() {
		return response;
	}
	public void setResponse(HttpServletResponse response) {
		this.response = response;
	}
	public void addMensagem(List<Alerta> alertas){
		for(Alerta alerta:alertas){
			addMensagem(alerta);
		}
	}
	public void addMensagem(Alerta alerta){
		((List<Alerta>) this.request.getAttribute(ContextAttributes.REQUEST_ALERTAS)).add(alerta);		
	}
	public void setMenuLateral(Object menuLateral) {
		this.setSessionAttribute("menuLateral", menuLateral);
	}
	public void setPage(String string) {
		this.setAttribute("page", string);
	}
	public void setLista(List<?> lista) {
		this.setAttribute("lista", lista);
	}
	public void setEntidade(EntidadeBase<?> entidade) {
		this.setAttribute("entidade", entidade);
		
	}
	public void setTitulo(String string) {
		this.setAttribute("titulo", string);
		
	}
	public void setSubTitulo(String string) {
		this.setAttribute("subTitulo", string);
		
	}
	public void setLegenda(String string) {
		this.setAttribute("legenda", string);
		
	}
	public int getDisplayTagPag(String listaName){
		try{
			return Integer.parseInt(getRequest().getParameter((new ParamEncoder(listaName).encodeParameterName(TableTagParameters.PARAMETER_PAGE))));
		}catch(Exception e){
			return 0;
		}
	}
	public int getDisplayTagSort(String listaName){
		try{
			return Integer.parseInt(request.getParameter(new ParamEncoder(listaName).encodeParameterName(TableTagParameters.PARAMETER_SORT)));
		}catch(Exception e){
			return 0;
		}
		
	}
	public int getDisplayTagOrder(String listaName){
		try{
			return Integer.parseInt(request.getParameter(new ParamEncoder(listaName).encodeParameterName(TableTagParameters.PARAMETER_ORDER)));
		}catch(Exception e){
			return 0;
		}
		
	}
}
